package com.apes.framework.plugin.filereader.xml;

import com.apes.framework.api.ApesParser;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.dom4j.Document;
import org.dom4j.Element;
import org.springframework.stereotype.Component;
import org.springframework.util.LinkedCaseInsensitiveMap;

import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * 功能：基于Dom4j的Xml文档解析器（xml -> node -> element）
 *
 * @author xul
 * @create 2018-04-16 13:42
 */
@Component
public class ApesXmlParser implements ApesParser<Document, List<ApesElement>> {
    protected static final Logger logger = LogManager.getLogger(ApesXmlParser.class);

    /**
     * 节点解析器
     **/
    private static final Map<String, ApesParser> nodeParsers = new LinkedCaseInsensitiveMap();

    /**
     * 元素解析器
     **/
    private static final Map<String, ApesParser> elementParsers = new LinkedCaseInsensitiveMap();

    /**
     * 功能：解析文档
     */
    @Override
    public List<ApesElement> parse(Document document){
        Element root = document.getRootElement();
        List<Element> elements = root.elements();
        return elements.stream().filter(element -> getApesNodeParser(element.getName()) != null)
                .map(element -> {
                    ApesParser nodeParser = getApesNodeParser(element.getName());
                    return (ApesElement) nodeParser.parse(element);
                }).collect(Collectors.toList());
    }

    public static void setApesElementParser(ApesElementParser parser) {
        for (String name : parser.getNames()) {
            String key = getKey(parser.getDomain(), name);
            elementParsers.put(key, parser);
        }
    }

    public static ApesParser getApesElementParser(String key) {
        return elementParsers.get(key);
    }

    public static void setApesNodeParser(ApesNodeParser parser) {
        for (String name : parser.getNames()) {
            nodeParsers.put(name, parser);
        }
    }

    public static ApesParser getApesNodeParser(String key) {
        return nodeParsers.get(key);
    }

    public static String getKey(String domain, String elementName) {
        domain = domain.contains(":") ? domain : domain + ":";
        return domain + elementName;
    }

}
